/**
 * 
 */
package optimization.naturalOptimization.particleSwarmOptimization.neighborhood;

import optimization.naturalOptimization.particleSwarmOptimization.ParticleSwarmOptimization;
import optimization.naturalOptimization.population.Population;
import optimization.naturalOptimization.population.individual.pso.Particle;

/**
 * Provides a neighborhood for the particle swarm algorithm where every particle
 * has two neighbors. All particles are arranged in a circle.
 * 
 * @author Kevin Wagner
 * @version 1.0
 */
public class CircleNeighborhood extends PSONeighborhood {

	/**
	 * Creates a new Neighborhood for a given PSO.
	 * 
	 * @param parentPSO
	 */
	public CircleNeighborhood(ParticleSwarmOptimization parentPSO) {
		super(parentPSO);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * optimization.naturalOptimization.particleSwarmOptimization.neighborhood
	 * .PSONeighborhood#setNeighborhoodbest()
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public void setNeighborhoodbest() {
		Particle[] best = new Particle[getParentPSO().getSwarmSize()];
		Population swarm = getParentPSO().getSwarm();
		for (int i = 0; i < getParentPSO().getSwarmSize(); i++) {
			best[i] = (Particle) swarm.getIndividual(i);
			if (i == 0) {
				if (getParentPSO().getFitness().compare(
						best[i].getPersonalBestFitness(),
						((Particle) swarm.getIndividual(i + 1))
								.getPersonalBestFitness()) == 2) {
					best[i] = (Particle) swarm.getIndividual(i + 1);
				}
				if (getParentPSO().getFitness().compare(
						best[i].getPersonalBestFitness(),
						((Particle) swarm.getIndividual(getParentPSO()
								.getSwarmSize() - 1)).getPersonalBestFitness()) == 2) {
					best[i] = (Particle) swarm.getIndividual(getParentPSO()
							.getSwarmSize() - 1);
				}
			} else if (i == getParentPSO().getSwarmSize() - 1) {
				if (getParentPSO().getFitness().compare(
						best[i].getPersonalBestFitness(),
						((Particle) swarm.getIndividual(i - 1))
								.getPersonalBestFitness()) == 2) {
					best[i] = (Particle) swarm.getIndividual(i - 1);
				}
				if (getParentPSO().getFitness().compare(
						best[i].getPersonalBestFitness(),
						((Particle) swarm.getIndividual(0))
								.getPersonalBestFitness()) == 2) {
					best[i] = (Particle) swarm.getIndividual(0);
				}
			} else {
				if (getParentPSO().getFitness().compare(
						best[i].getPersonalBestFitness(),
						((Particle) swarm.getIndividual(i + 1))
								.getPersonalBestFitness()) == 2) {
					best[i] = (Particle) swarm.getIndividual(i + 1);
				}
				if (getParentPSO().getFitness().compare(
						best[i].getPersonalBestFitness(),
						((Particle) swarm.getIndividual(i - 1))
								.getPersonalBestFitness()) == 2) {
					best[i] = (Particle) swarm.getIndividual(i - 1);
				}
			}
		}
		for (int i = 0; i < getParentPSO().getSwarmSize(); i++) {
			((Particle) swarm.getIndividual(i)).setNeighborhoodBest(best[i]
					.getPersonalBest());
			((Particle) swarm.getIndividual(i))
					.setNeighborhoodBestFitness(best[i]
							.getPersonalBestFitness());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see optimization.IdentificationI#getIndentification()
	 */
	@Override
	public String getIndentification() {
		return "Circle";
	}

}
